﻿using System;
using System.Data;

namespace MyLib {
	/// <summary>
	/// 
	/// </summary>
	public class MySqlSessionFactory : SessionFactory {
		/// <summary>
		/// 
		/// </summary>
		/// <param name="parameter"></param>
		/// <returns></returns>
		protected override System.Data.IDbDataParameter CreateParameter(DbParameter parameter) {
			var p = Factory.CreateParameter();

			p.ParameterName = ParameterPrefix + parameter.Name;

			if (parameter.DbType == DbParameterType.StartDate) {
				// Pre-format StartDate parameter.
				// For mysql.
				p.DbType = DbType.DateTime;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = DBNull.Value;
				} else {
					var dt = Convert.ToDateTime(parameter.Value);
					if (UseGMT) {
						p.Value = new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0).ToUniversalTime();
					} else {
						p.Value = new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0);
					}
				}
			} else if (parameter.DbType == DbParameterType.StartMonth) {
				// Pre-format StartMonth parameter.
				// For mysql.
				p.DbType = DbType.DateTime;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = DBNull.Value;
				} else {
					var dt = Convert.ToDateTime(parameter.Value);
					if (UseGMT) {
						p.Value = new DateTime(dt.Year, dt.Month, 1, 0, 0, 0).ToUniversalTime();
					} else {
						p.Value = new DateTime(dt.Year, dt.Month, 1, 0, 0, 0);
					}
				}
			} else if (parameter.DbType == DbParameterType.StartYear) {
				// Pre-format StartYear parameter.
				// For mysql.
				p.DbType = DbType.DateTime;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = DBNull.Value;
				} else {
					var dt = Convert.ToDateTime(parameter.Value);
					if (UseGMT) {
						p.Value = new DateTime(dt.Year, 1, 1, 0, 0, 0).ToUniversalTime();
					} else {
						p.Value = new DateTime(dt.Year, 1, 1, 0, 0, 0);
					}
				}
			} else if (parameter.DbType == DbParameterType.EndDate) {
				// Pre-format EndDate parameter.
				// For mysql.
				p.DbType = DbType.DateTime;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = DBNull.Value;
				} else {
					var dt = Convert.ToDateTime(parameter.Value);
					if (UseGMT) {
						p.Value = new DateTime(dt.Year, dt.Month, dt.Day, 23, 59, 59).ToUniversalTime();
					} else {
						p.Value = new DateTime(dt.Year, dt.Month, dt.Day, 23, 59, 59);
					}
				}
			} else if (parameter.DbType == DbParameterType.EndMonth) {
				// Pre-format EndMonth parameter.
				// For mysql.
				p.DbType = DbType.DateTime;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = DBNull.Value;
				} else {
					var dt = Convert.ToDateTime(parameter.Value);
					if (UseGMT) {
						p.Value = new DateTime(dt.Year, dt.Month, DateTime.DaysInMonth(dt.Year, dt.Month), 23, 59, 59).ToUniversalTime();
					} else {
						p.Value = new DateTime(dt.Year, dt.Month, DateTime.DaysInMonth(dt.Year, dt.Month), 23, 59, 59);
					}
				}
			} else if (parameter.DbType == DbParameterType.EndYear) {
				// Pre-format EndYear parameter.
				// For mysql.
				p.DbType = DbType.DateTime;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = DBNull.Value;
				} else {
					var dt = Convert.ToDateTime(parameter.Value);
					if (UseGMT) {
						p.Value = new DateTime(dt.Year, 12, 31, 23, 59, 59).ToUniversalTime();
					} else {
						p.Value = new DateTime(dt.Year, 12, 31, 23, 59, 59);
					}
				}
			} else if (parameter.DbType == DbParameterType.String && parameter.MatchType != DbParameterMatchType.Exact) {
				// Escape String for non-exact match.
				// For mysql.
				p.DbType = DbType.String;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = "";
				} else {
					var ostr = Convert.ToString(parameter.Value);
					p.Value = ostr.Replace(@"\", @"\\").Replace(@"%", @"\%").Replace(@"_", @"\_");
				}
			} else if (parameter.DbType == DbParameterType.String && parameter.MatchType == DbParameterMatchType.Exact) {
				p.DbType = DbType.String;
				p.Value = parameter.Value;
			} else if (parameter.DbType == DbParameterType.Integer) {
				p.DbType = DbType.Int32;
				p.Value = parameter.Value;
			} else if (parameter.DbType == DbParameterType.Long) {
				p.DbType = DbType.Int64;
				p.Value = parameter.Value;
			} else if (parameter.DbType == DbParameterType.Decimal) {
				p.DbType = DbType.Decimal;
				p.Value = parameter.Value;
			} else if (parameter.DbType == DbParameterType.DateTime) {
				p.DbType = DbType.DateTime;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = DBNull.Value;
				} else {
					var dt = Convert.ToDateTime(parameter.Value);
					if (UseGMT) {
						p.Value = dt.ToUniversalTime();
					} else {
						p.Value = dt;
					}
				}
			} else if(parameter.DbType == DbParameterType.Date) {
				p.DbType = DbType.DateTime;
				if (parameter.Value == null || parameter.Value == DBNull.Value) {
					p.Value = DBNull.Value;
				} else {
					var dt = Convert.ToDateTime(parameter.Value);
					dt = new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0);
					if (UseGMT) {
						p.Value = dt.ToUniversalTime();
					} else {
						p.Value = dt;
					}
				}
			} else if (parameter.DbType == DbParameterType.Float) {
				p.DbType = DbType.Single;
				p.Value = parameter.Value;
			} else if (parameter.DbType == DbParameterType.Double) {
				p.DbType = DbType.Double;
				p.Value = parameter.Value;
			} else if (parameter.DbType == DbParameterType.Bool) {
				p.DbType = DbType.Boolean;
				p.Value = parameter.Value;
			} else if (parameter.DbType == DbParameterType.Binary) {
				p.DbType = DbType.Binary;
				p.Value = parameter.Value;
			} else {
				throw new InvalidOperationException(
					string.Format(
						@"Unknown db type ""{0}"" of parameter ""{1}"".", parameter.DbType, parameter.Name));
			}

			p.Direction = parameter.Direction;
			return p;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="connectionString"></param>
		public MySqlSessionFactory(string connectionString)
			: base(MySql.Data.MySqlClient.MySqlClientFactory.Instance, connectionString, "@", true) {
		}
	} // end of MySqlSessionFactory.
}
